package ks.client.processor;

import org.w3c.dom.Node;

import ks.client.Initializer;
import ks.client.controllers.requests.AccountUpdateController;
import ks.client.controllers.requests.AckController;
import ks.client.controllers.requests.ConfirmController;
import ks.client.controllers.requests.ConnectingController;
import ks.client.controllers.requests.DisconnectingController;
import ks.client.controllers.requests.FinishedController;
import ks.client.controllers.requests.IconsController;
import ks.client.controllers.requests.JoinedController;
import ks.client.controllers.requests.KickedController;
import ks.client.controllers.requests.LeftController;
import ks.client.controllers.requests.ModeratorController;
import ks.client.controllers.requests.OutputController;
import ks.client.controllers.requests.PluginInstalledController;
import ks.client.controllers.requests.PluginsController;
import ks.client.controllers.requests.StartedController;
import ks.client.controllers.requests.TableClearController;
import ks.client.controllers.requests.TableInfoController;
import ks.client.controllers.requests.TableOptionsController;
import ks.client.controllers.requests.TableOutputController;
import ks.client.controllers.requests.UpdatedController;
import ks.client.controllers.requests.UsersController;
import ks.client.lobby.Lobby;
import ks.framework.common.Message;
import ks.framework.interfaces.IClientProcessor;

/**
 * Client-side processor of messages received from Server.
 * <p>
 * This must be altered properly to be able to handle the wide variety
 * of requests being received from the server. This is a design 
 * issue that will be addressed at its proper time.
 * 
 * @author George Heineman
 * @author Jennifer Hunt
 * @author Christopher Page
 * @author Samir Zutshi
 */
public class Processor implements IClientProcessor {

	/** The core Processor knows about the Lobby for which it is in control. */
	Lobby lobby;

	/** 
	 * Each processor knows the lobby for which it is responsible.
	 * 
	 * @param lob
	 */
	public Processor (Lobby lob) {
		this.lobby = lob;
	}

	@Override
	public boolean process(Message m) {
		System.out.println("Recieved message: " + m.toString());
		
		// account-update
		if (m.getName().equalsIgnoreCase("account-update"))
			return new AccountUpdateController(lobby).process(m);
		
		// confirm
		if (m.getName().equalsIgnoreCase("confirm"))
			return new ConfirmController(lobby).process(m);
		
		// connecting
		if (m.getName().equalsIgnoreCase("connecting"))
			return new ConnectingController(lobby).process(m);
		
		// disconnecting
		if (m.getName().equalsIgnoreCase("disconnecting"))
			return new DisconnectingController(lobby).process(m);
		
		// finished
		if (m.getName().equalsIgnoreCase("finished"))
			return new FinishedController(lobby).process(m);
		
		// icons
		if (m.getName().equalsIgnoreCase("icons"))
			return new IconsController(lobby).process(m);
		
		// joined
		if (m.getName().equalsIgnoreCase("joined"))
			return new JoinedController(lobby).process(m);

		// kicked
		if (m.getName().equalsIgnoreCase("kicked"))
			return new KickedController(lobby).process(m);

		// left
		if (m.getName().equalsIgnoreCase("left"))
			return new LeftController(lobby).process(m);

		// moderator
		if (m.getName().equalsIgnoreCase("moderator"))
			return new ModeratorController(lobby).process(m);

		// output
		if (m.getName().equalsIgnoreCase("output"))
			return new OutputController(lobby).process(m);
		

		// plugin-installed
		if (m.getName().equalsIgnoreCase("plugin-installed"))
			return new PluginInstalledController(lobby).process(m);

		// plugins
		if (m.getName().equalsIgnoreCase("plugins"))
			return new PluginsController(lobby).process(m);

		//TODO implement following controller
		// rejected
		if (m.getName().equalsIgnoreCase("rejected"))
			return false;
		
		//TODO implement following controller
		// started
		if (m.getName().equalsIgnoreCase("started"))
			return false;
		
		// table-clear
		if (m.getName().equalsIgnoreCase("table-clear"))
			return new TableClearController(lobby).process(m);

		// table-info
		if (m.getName().equalsIgnoreCase("table-info"))
			return new TableInfoController(lobby).process(m);

		// table-options
		if (m.getName().equalsIgnoreCase("table-options"))
			return new TableOptionsController(lobby).process(m);

		// table-output
		if(m.getName().equalsIgnoreCase("table-output"))
			return new TableOutputController(lobby).process(m);

		// updated
		if (m.getName().equalsIgnoreCase("updated"))
			return new UpdatedController(lobby).process(m);

		// users
		if (m.getName().equalsIgnoreCase("users"))
			return new UsersController(lobby).process(m);
		
		// other request controllers would go here...
		
		// note that you will LIKELY need to deal specially with ACK and NACK 
		// requests because they refer to commands that have been sent to the server
		// which either succeeded (or failed) and you will need to know about this.
		
		// Therefore you will likely need some sort of registration scheme that keeps
		// track of commands sent (by their unique ID) and can match up against the 
		// received ACK and NACK. These details will become much clearer during Implementation
		// so don't worry about it right now for design.
		
		// this is here for debugging purposes. You will likely need
		// to have some means for reacting to nack events as necessary
		if (m.getName().equalsIgnoreCase("nack")) {
			Node output = m.contents();
			String s = "Nack Received:" + output.getTextContent();
			lobby.append(s);
			return true;
		} 

		// this is here for debugging purposes. You will likely need
		// to have some means for reacting to ack events as necessary
		if (m.getName().equalsIgnoreCase("ack")) {
			return new AckController(lobby).process(m);
		}
		
		return false;
	}

	/**
	 * Connection has been made. Tell lobby.
	 * 
	 * @param status
	 */
	public void connected(boolean status) {
		lobby.connected(status);
		
		Initializer.init(lobby);
	}
}
